home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
050
/
bix02.arc
/
PRINTER.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1986-08-04
|
6KB
|
198 lines
{various parallel printer handling and error-checking}
PROGRAM Printer;
{-demonstrate print error control}
{***********************************************************************
the following can be included verbatim into a program}
TYPE
Printers = (LPT1, LPT2, LPT3, LPT4, NoPrinter);
CONST
ActivePrinter : Printers = NoPrinter;
VAR
SavePrintTimeOut : Byte;
{
the following bytes normally equal $14, providing 20 retries on printer
busy calls. Set to 1 for a single retry (timeout takes about 2 seconds).
Do not set to 0 or system will retry forever.
}
PrintTimeOut : ARRAY[Printers] OF Byte ABSOLUTE $40 : $78;
PROCEDURE PrintChar(ch : Char);
{-print the character ch, handle errors and loop when busy}
{
**********************************************************************
CANNOT USE TURBO I/O FUNCTIONS INSIDE HERE DUE TO RE-ENTRANCY PROBLEMS
**********************************************************************
}
TYPE
PrintErrors =
(TimeOut, unused1, unused2, IOerror, Selected,
OutOfPaper, Acknowledge, Busy, NoError);
DisplayString = STRING[80];
registers =
RECORD
CASE Integer OF
1 : (ax, bx, cx, dx, bp, si, di, ds, es, flags : Integer);
2 : (al, ah, bl, bh, cl, ch, dl, dh : Byte);
END;
CONST
PrintErrorMsg : ARRAY[PrintErrors] OF DisplayString =
('Printer Timeout Error', '', '', 'Printer Not Selected',
'Printer Not Selected', 'Printer Out of Paper',
'Printer Acknowledge Error', 'Printer Busy', '');
EndStr : DisplayString = #13#10#36;
{maximum number of replies with busy before calling it a timeout error.
may need to be adjusted empirically to avoid false timeouts}
BusyMax = 100;
VAR
reg : registers;
Error : PrintErrors;
BusyCount : Integer;
PROCEDURE writestring(s : DisplayString);
{-write string to standard output}
VAR
reg : registers;
BEGIN
reg.ah := 9;
reg.ds := Seg(s);
reg.dx := Ofs(s[1]);
MsDos(reg);
END; {displaystring}
PROCEDURE getchar(VAR response : Char);
{-get a character from the keyboard}
VAR
reg : registers;
BEGIN
reg.ah := 0;
Intr($16, reg);
response := Chr(reg.al);
END; {getchar}
FUNCTION AnyError(VAR Error : PrintErrors)
: Boolean;
{-check all the possible printer errors}
{-return TRUE and error if any found}
FUNCTION SingleError(check : PrintErrors; VAR Error : PrintErrors)
: Boolean;
{-return true if specified error was found, setting error}
BEGIN
SingleError := ((1 SHL Ord(check)) AND reg.ah) <> 0;
Error := check;
END; {singleerror}
BEGIN
AnyError := True;
IF SingleError(Busy, Error) THEN Exit;
IF SingleError(OutOfPaper, Error) THEN Exit;
IF SingleError(IOerror, Error) THEN Exit;
{polarity of "selected" flag is opposite of others}
IF NOT(SingleError(Selected, Error)) THEN Exit;
{made it through with no errors}
Error := NoError;
AnyError := False;
END; {anyerror}
PROCEDURE HandleError(VAR Error : PrintErrors);
{-handle user-oriented error conditions}
VAR
response : Char;
BEGIN
IF (Error = NoError) THEN Exit;
IF (Error = Busy) THEN BEGIN
BusyCount := Succ(BusyCount);
IF BusyCount < BusyMax THEN Exit;
{busy too long, call it a timeout}
Error := TimeOut;
END;
{
prompt user to correct the error condition. screen handling could
be much fancier here but it cannot use Turbo I/O functions.
}
writestring(PrintErrorMsg[Error]+EndStr);
writestring('Correct condition and then press <ENTER> '+#36);
REPEAT
getchar(response);
UNTIL (response IN [#13, #3]);
writestring(EndStr);
IF response = #3 THEN Halt; {Ctrl-C}
BusyCount := 0;
END; {handleerror}
BEGIN
IF ActivePrinter = NoPrinter THEN BEGIN
writestring('program error: no printer is selected'+EndStr);
Exit;
END;
reg.dx := Ord(ActivePrinter); {equals 0..3}
BusyCount := 0;
REPEAT
{check printer status}
reg.ah := 2;
Intr($17, reg);
{check for errors}
IF AnyError(Error) AND (Error <> Busy) THEN
HandleError(Error)
ELSE BEGIN
{print the character}
reg.ax := Ord(ch);
Intr($17, reg);
{check for errors again}
IF AnyError(Error) THEN
HandleError(Error);
END;
UNTIL Error = NoError;
END; {printchar}
PROCEDURE ProtectPrinter(Printer : Printers);
{-define the Lst device to print to the specified printer}
BEGIN
IF ActivePrinter = NoPrinter THEN BEGIN
ActivePrinter := Printer;
LstOutPtr := Ofs(PrintChar);
{save current printer timeout}
SavePrintTimeOut := PrintTimeOut[Printer];
{set to minimum timeout period}
PrintTimeOut[Printer] := 1;
END ELSE
WriteLn(Con,
'program error: only one printer can be protected at a time');
END; {protectprinter}
PROCEDURE RestorePrinter;
{-deassign the Lst device and restore the printer timeout}
BEGIN
IF ActivePrinter <> NoPrinter THEN BEGIN
PrintTimeOut[ActivePrinter] := SavePrintTimeOut;
ActivePrinter := NoPrinter;
END;
END; {restoreprinter}
{end of include portion
***********************************************************************}
{demonstration follows}
VAR
i : Integer;
BEGIN
ProtectPrinter(LPT1);
FOR i := 1 TO 5 DO
{any writes to the Lst device are now protected}
WriteLn(Lst, 'hello hello hello hello');
RestorePrinter;
END.